package com.sens.alipay;

import android.content.Context;
import android.graphics.Color;

import com.sens.alipay.utils.AlipayUtils;
import com.sens.alipay.utils.OrderUtil;
import com.sens.alipay.utils.SupportVersion;
import com.sens.alipay.utils.TradeInfoHelper;
import com.sens.bean.AlipayTrade;
import com.sens.common.ApplicationUtil;
import com.sens.common.Base64;
import com.sens.common.BaseHooker;
import com.sens.common.Config;
import com.sens.common.JsonUtils;
import com.sens.common.Log;
import com.sens.common.StringUtil;
import com.sens.database.LiteOrmDBUtil;
import com.sens.ipc.alipay.IPCHelper;
import com.sens.ipc.alipay.application.Handle;
import com.sens.ipc.alipay.hooker.Callback;
import com.sens.network.AlipayOrderCallback;
import com.sens.network.ApiByHttp;
import com.sens.network.ResponseCallback;
import com.sens.tables.AliPayConfig;
import com.sens.tables.AlipayOrder;
import com.sens.tables.CommonConfig;
import com.sens.vo.AliPayOrderVo;
import com.yanzhenjie.nohttp.Logger;
import com.yanzhenjie.nohttp.NoHttp;
import com.yanzhenjie.nohttp.rest.Response;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;

import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XC_MethodReplacement;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class AlipayHooker extends BaseHooker implements Callback {
    public AlipayHooker() {
        super(new String(Base64.decode("Y29tLmVnLmFuZHJvaWQuQWxpcGF5R3Bob25l")));
    }

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
    private Handle handle;
    private Context context;
    private ClassLoader classLoader;
    private CommonConfig commonConfig;
    private AliPayConfig aliPayConfig;
    private boolean hasHook;

    private XC_MethodHook aW5zZXJ0TWVzc2FnZUluZm8sHook = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            if (StringUtil.isEmpty(aliPayConfig.getMonitorType())) return;
            String cookie = checkCookie();
            aliPayConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(AliPayConfig.class);
            if (aliPayConfig != null) {
                aliPayConfig.setAlipayCookie(AlipayUtils.getCookieStr(classLoader));
                LiteOrmDBUtil.getGlobalDBUtil(context).update(aliPayConfig);
            }
            Log.i("--->支付宝S订单start<---");
            //获取全部字段
            Object object = param.args[0];
            if (Config.ISDEBUG)
                Log.i(JsonUtils.parserBean2Json(object));
            String extraInfoString = (String) object.getClass().getField("extraInfo").get(object);
            if (extraInfoString.startsWith("{") && extraInfoString.endsWith("}")) {
                JSONObject extraInfo = new JSONObject(extraInfoString);
                String bizMonitorString = extraInfo.getString("bizMonitor");
                JSONObject bizMonitor = new JSONObject(bizMonitorString);
                String title = bizMonitor.getString("title");
                if ("商家服务·收款到账".equals(title)) {
                    AliPayOrderVo aliPayOrderVo = new AliPayOrderVo();
                    aliPayOrderVo.setMark(bizMonitor.getString("userId"));
                    aliPayOrderVo.setMarkType(aliPayConfig.getMonitorType());
                    aliPayOrderVo.setUserId(bizMonitor.getString("userId"));

                    aliPayOrderVo.setPayType("2");

                    aliPayOrderVo.setTradeNo(bizMonitor.getString("msgId"));
                    aliPayOrderVo.setMoney(extraInfo.getString("mainAmount"));
//                    aliPayOrderVo.setMark((aliPayOrderVo.getMark() == null ? "" : aliPayOrderVo.getMark()) + "-来自" + order.getConsumerName());
                    aliPayOrderVo.setTime(simpleDateFormat.format(bizMonitor.getLong("gmtCreate")));

                    handle.addOrder(aliPayOrderVo);
                    if (!"1000100101".equals(aliPayOrderVo.getUserId())) {
                        AlipayOrder alipayOrder = OrderUtil.createAlipayOrder(aliPayOrderVo);
                        LiteOrmDBUtil.getGlobalDBUtil(context).save(alipayOrder);
                        ApiByHttp.getInstance().uploadAlipayOrder(alipayOrder, new AlipayOrderCallback(context, alipayOrder.getTradeNo()) {
                            @Override
                            protected void onComplete(boolean isSuccess, String tradeNo, String msg) {
                                super.onComplete(isSuccess, tradeNo, msg);
                                handle.noticeMessage(msg + ":" + tradeNo);
                            }
                        });
                    }
//                    ApiByHttp.getInstance().queryAlipayOrder(1, 10, cookie, new BusinessTradeInfoCallback(aliPayOrderVo));
                }
            }
            Log.i("--->支付宝S订单end<---");
        }
    };

    private class BusinessTradeInfoCallback extends ResponseCallback<AlipayTrade> {
        private AliPayOrderVo aliPayOrderVo;
        private boolean hasRetry;

        BusinessTradeInfoCallback(AliPayOrderVo aliPayOrderVo) {
            this.aliPayOrderVo = aliPayOrderVo;
        }

        @Override
        public void onSucceed(int what, Response<AlipayTrade> response) {
            super.onSucceed(what, response);
            if (response.get() != null && response.get().getResult() != null && response.get().getResult().getList() != null && response.get().getResult().getList().size() > 0) {
                AlipayTrade.Data.Order order = response.get().getResult().getList().get(0);
                aliPayOrderVo.setTradeNo(order.getTradeNo());
                aliPayOrderVo.setMoney(order.getTotalPayedAmount());
                aliPayOrderVo.setMark((aliPayOrderVo.getMark() == null ? "" : aliPayOrderVo.getMark()) + "-来自" + order.getConsumerName());
                aliPayOrderVo.setTime(simpleDateFormat.format(order.getGmtCreateStamp()));
                handle.addOrder(aliPayOrderVo);
                if (!"1000100101".equals(aliPayOrderVo.getUserId())) {
                    AlipayOrder alipayOrder = OrderUtil.createAlipayOrder(aliPayOrderVo);
                    LiteOrmDBUtil.getGlobalDBUtil(context).save(alipayOrder);
                    ApiByHttp.getInstance().uploadAlipayOrder(alipayOrder, new AlipayOrderCallback(context, alipayOrder.getTradeNo()) {
                        @Override
                        protected void onComplete(boolean isSuccess, String tradeNo, String msg) {
                            super.onComplete(isSuccess, tradeNo, msg);
                            handle.noticeMessage(msg + ":" + tradeNo);
                        }
                    });
                }
            }else onFailed(what,response);
        }

        @Override
        public void onFailed(int what, Response<AlipayTrade> response) {
            super.onFailed(what, response);
            if (hasRetry) {
                handle.addOrder(aliPayOrderVo);
                if (!"1000100101".equals(aliPayOrderVo.getUserId())) {
                    AlipayOrder alipayOrder = OrderUtil.createAlipayOrder(aliPayOrderVo);
                    LiteOrmDBUtil.getGlobalDBUtil(context).save(alipayOrder);
                    ApiByHttp.getInstance().uploadAlipayOrder(alipayOrder, new AlipayOrderCallback(context, alipayOrder.getTradeNo()) {
                        @Override
                        protected void onComplete(boolean isSuccess, String tradeNo, String msg) {
                            super.onComplete(isSuccess, tradeNo, msg);
                            handle.noticeMessage(msg + ":" + tradeNo);
                        }
                    });
                }
                return;
            }
            hasRetry = true;
            try {
                String cookie = checkCookie();
                ApiByHttp.getInstance().queryAlipayOrder(1, 1, cookie, this);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private XC_MethodHook aW5zZXJ0TWVzc2FnZUluZm8Hook = new XC_MethodHook() {
        @Override
        protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
            if (StringUtil.isEmpty(aliPayConfig.getMonitorType())) return;
            checkCookie();
            Log.i("--->支付宝订单start<---");
            //获取全部字段
            Object object = param.args[0];
            if (Config.ISDEBUG)
                Log.i(JsonUtils.parserBean2Json(object));
            JSONObject extraInfo = new JSONObject((String) object.getClass().getField("extraInfo").get(object));
            String status = extraInfo.getString("status");
            if (status.equals("二维码收款到账通知") || status.equals("收到一笔转账")) {
                String tradeNo = StringUtil.getTextCenter((String) object.getClass().getField("link").get(object), "tradeNO=", "&");
                String mark = null;
                String time = null;
                JSONArray contentArray = extraInfo.getJSONArray("content");
                for (int i = 0; i < contentArray.length(); i++) {
                    JSONObject contentItem = contentArray.getJSONObject(i);
                    String title = contentItem.getString("title");
                    if (title.equals(aliPayConfig.getMonitorType())) {
                        mark = contentItem.getString("content");
                        //收款理由：商品说明：转账备注：
                    } else if ("到账时间：".equals(contentItem.getString("title"))) {
                        time = contentItem.getString("content");
                    }
                }
                if (mark != null && time != null) {
                    AliPayOrderVo aliPayOrderVo = new AliPayOrderVo();
                    aliPayOrderVo.setTradeNo(tradeNo);
                    aliPayOrderVo.setMark(mark);
                    aliPayOrderVo.setMarkType(aliPayConfig.getMonitorType());
                    aliPayOrderVo.setTime(time);
                    aliPayOrderVo.setMoney(extraInfo.getString("money"));
                    aliPayOrderVo.setPayType("1");
                    aliPayOrderVo.setUnit(extraInfo.getString("unit"));
                    aliPayOrderVo.setUserId((String) object.getClass().getField("userId").get(object));
                    if (!"1000100101".equals(aliPayOrderVo.getUserId())) {
                        AlipayOrder alipayOrder = OrderUtil.createAlipayOrder(aliPayOrderVo);
                        LiteOrmDBUtil.getGlobalDBUtil(context).save(alipayOrder);
                        ApiByHttp.getInstance().uploadAlipayOrder(alipayOrder, new AlipayOrderCallback(context, alipayOrder.getTradeNo()) {
                            @Override
                            protected void onComplete(boolean isSuccess, String tradeNo, String msg) {
                                super.onComplete(isSuccess, tradeNo, msg);
                                handle.noticeMessage(msg + ":" + tradeNo);
                            }
                        });
                    }
                    Log.i("直接回传");
                    handle.addOrder(aliPayOrderVo);
                }
            }
            Log.i("--->支付宝订单end<---");
        }
    };

    private XC_MethodHook b25DcmVhdGUHooker = new XC_MethodHook() {
        @Override
        protected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {
            super.afterHookedMethod(param);
            Log.i("onCreate--->" + param.thisObject.getClass().getName());
            context = (Context) param.thisObject;
            if (hasHook) return;
            hasHook = true;
            if (SupportVersion.checkSupportable(ApplicationUtil.getVersionName(context))) {
                classLoader = context.getClassLoader();
                Logger.setDebug(Config.ISDEBUG);
                NoHttp.initialize(context.getApplicationContext());
                aliPayConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(AliPayConfig.class);
                if (aliPayConfig == null) {
                    aliPayConfig = new AliPayConfig();
                    LiteOrmDBUtil.getGlobalDBUtil(context).save(aliPayConfig);
                    aliPayConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(AliPayConfig.class);
                }
                commonConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(CommonConfig.class);
                if (commonConfig != null) {
                    ApiByHttp.getInstance().setHost(commonConfig.getServiceHost());
                } else {
                    commonConfig = new CommonConfig();
                    LiteOrmDBUtil.getGlobalDBUtil(context).save(commonConfig);
                    commonConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(CommonConfig.class);
                }
                if (handle != null) handle.unBind();
                handle = IPCHelper.getApplicationHandle(context, AlipayHooker.this);
                handle.requestMonitor();
                Log.i("hook支付宝");
                securityCheckHook(classLoader);
                XposedHelpers.findAndHookMethod(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRhby5UcmFkZURhbw")), classLoader, new String(Base64.decode("aW5zZXJ0TWVzc2FnZUluZm8")), XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRiLlRyYWRlSW5mbw")), classLoader), String.class, aW5zZXJ0TWVzc2FnZUluZm8Hook);
                XposedHelpers.findAndHookMethod(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRhby5TZXJ2aWNlRGFv")), classLoader, new String(Base64.decode("aW5zZXJ0TWVzc2FnZUluZm8")), XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRiLlNlcnZpY2VJbmZv")), classLoader), String.class, aW5zZXJ0TWVzc2FnZUluZm8sHook);
//                new TestHooker(classLoader);
            }
        }
    };

    @Override
    public void handlePackage(final XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {
        if (lpparam.isFirstApplication)
            XposedHelpers.findAndHookMethod(XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5tb2JpbGUucXVpbm94LkxhdW5jaGVyQXBwbGljYXRpb24")), lpparam.classLoader), new String(Base64.decode("b25DcmVhdGU")), b25DcmVhdGUHooker);
    }

    private String checkCookie() throws Exception {
        String cookie = AlipayUtils.getCookieStr(classLoader);
        if (cookie != null) {
            aliPayConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(AliPayConfig.class);
            if (aliPayConfig != null) {
                aliPayConfig.setAlipayCookie(cookie);
                LiteOrmDBUtil.getGlobalDBUtil(context).update(aliPayConfig);
            }
        }
        return cookie;
    }

    private void securityCheckHook(ClassLoader classLoader) {
        try {
            Class<?> securityCheckClazz = XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5tb2JpbGUuYmFzZS5zZWN1cml0eS5DSQ")), classLoader);
            XposedHelpers.findAndHookMethod(securityCheckClazz, "a", String.class, String.class, String.class, new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    Object object = param.getResult();
                    XposedHelpers.setBooleanField(object, "a", false);
                    param.setResult(object);
                    super.afterHookedMethod(param);
                }
            });

            XposedHelpers.findAndHookMethod(securityCheckClazz, "a", Class.class, String.class, String.class, new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    return (byte) 1;
                }
            });
            XposedHelpers.findAndHookMethod(securityCheckClazz, "a", ClassLoader.class, String.class, new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    return (byte) 1;
                }
            });
            XposedHelpers.findAndHookMethod(securityCheckClazz, "a", new XC_MethodReplacement() {
                @Override
                protected Object replaceHookedMethod(MethodHookParam param) throws Throwable {
                    return false;
                }
            });

        } catch (Error | Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void startQuartz() {
        QuartzJob.start(context);
    }

    @Override
    public void checkUserId() {
        handle.updateUserId(AlipayUtils.getUserId(classLoader));
    }

    @Override
    public void setMonitor(String monitor) {
        aliPayConfig = LiteOrmDBUtil.getGlobalDBUtil(context).queryOne(AliPayConfig.class);
        if (aliPayConfig != null) {
            if (aliPayConfig.getMonitorType() != null && aliPayConfig.getMonitorType().equals(monitor))
                return;
            aliPayConfig.setMonitorType(monitor);
            LiteOrmDBUtil.getGlobalDBUtil(context).update(aliPayConfig);
        }
    }

    @Override
    public void setHost(String host) {
        ApiByHttp.getInstance().setHost(host);
    }

    @Override
    public void test() {
        if (aliPayConfig.getMonitorType() == null) {
            handle.noticeMessage(StringUtil.createColorText(Color.RED, "还未设置采集方式"));
            handle.requestMonitor();
            return;
        }
        try {
            Class TradeInfoClass = XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRiLlRyYWRlSW5mbw")), classLoader);
            TradeInfoHelper tradeInfoHelper = OrderUtil.createTestOrder(TradeInfoClass, aliPayConfig.getMonitorType());
            Class<?> TradeDaoClass = XposedHelpers.findClass(new String(Base64.decode("Y29tLmFsaXBheS5hbmRyb2lkLnBob25lLm1lc3NhZ2Vib3hzdGF0aWMuYml6LmRhby5UcmFkZURhbw")), classLoader);
            Method getDaoMethod = TradeDaoClass.getMethod("getDao");
            Object tradeDao = getDaoMethod.invoke(null);
            Method insertMessageInfo = TradeDaoClass.getMethod("insertMessageInfo", TradeInfoClass, String.class);
            insertMessageInfo.invoke(tradeDao, tradeInfoHelper.getTradeInfo(), "1000100101");
        } catch (Throwable e) {
            handle.noticeMessage(StringUtil.createColorText(Color.RED, "模拟数据失败"));
            e.printStackTrace();
        }
    }

}
